#include "urltasks.h"

#include <QtAlgorithms>
#include <QDebug>

UrlTasks::UrlTasks(QObject *parent)
    : QAbstractTableModel(parent)
{
    m_settings.load_urls(this);
}

UrlTasks::~UrlTasks()
{
    m_settings.save_urls(m_tasks);
}

template <typename T, typename R, typename M = R (T::*)() const>
struct less_then
{
    struct local_less
    {
        local_less(Qt::SortOrder order)
            : m_order(order) {}

        bool operator()(R const &l, R const &r) const
        {
            if (m_order == Qt::AscendingOrder) return l < r;
            else return l > r;
        }

        Qt::SortOrder m_order;
    };

    less_then(Qt::SortOrder order, M getter)
        : m_cmp(order), m_getter(getter) {}

    bool operator()(T const &l, T const &r) const
    {
        return m_cmp((l.*m_getter)(), (r.*m_getter)());
    }

    local_less m_cmp;
    M m_getter;
};

template <typename T, typename R>
less_then<T, R, R (T::*)() const> make_cmp(Qt::SortOrder order, R (T::*getter)() const)
{
    return less_then<T, R, R (T::*)() const>(order, getter);
}

void UrlTasks::sort(int column, Qt::SortOrder order)
{
    switch (column)
    {
    case UrlTask::STATUS:
    {
        qStableSort(m_tasks.begin(), m_tasks.end(), make_cmp(order, &UrlTask::get_status));
        break;
    }
    case UrlTask::URL:
    {
        qStableSort(m_tasks.begin(), m_tasks.end(), make_cmp(order, &UrlTask::get_url));
        break;
    }
    case UrlTask::PROGRESS:
    {
        qStableSort(m_tasks.begin(), m_tasks.end(), make_cmp(order, &UrlTask::get_progress));
        break;
    }
    case UrlTask::FILE:
    {
        qStableSort(m_tasks.begin(), m_tasks.end(), make_cmp(order, &UrlTask::get_file));
        break;
    }
    }
    emit layoutChanged();
}

int UrlTasks::rowCount(const QModelIndex &) const
{
    return m_tasks.size();
}

int UrlTasks::columnCount(const QModelIndex &) const
{
    return UrlTask::LAST;
}

QVariant UrlTasks::data(const QModelIndex &index, int) const
{
    UrlTask const &row = m_tasks[index.row()];
    switch (index.column())
    {
    case UrlTask::STATUS: return QVariant(row.get_status());
    case UrlTask::URL: return QVariant(row.get_url());
    case UrlTask::FILE: return QVariant(row.get_file());
    case UrlTask::PROGRESS: return QVariant(row.get_progress());
    }
    return QVariant();
}

QModelIndex UrlTasks::index(int row, int column, const QModelIndex &) const
{
    return createIndex(row, column, const_cast<UrlTask *>(&m_tasks[row]));
}

QVariant UrlTasks::headerData(int section, Qt::Orientation orientation, int role) const
{
    if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
    {
        switch (section)
        {
        case UrlTask::STATUS: return QVariant(tr("status", "table header"));
        case UrlTask::URL: return QVariant(tr("url", "table header"));
        case UrlTask::PROGRESS: return QVariant(tr("progress", "table header"));
        case UrlTask::FILE: return QVariant(tr("file", "table header"));
        }
    }
    return QVariant();
}

void UrlTasks::create_new_task(const QString &url, const QString &file, UrlTask::TaskStatus status)
{
    beginInsertRows(QModelIndex(), 0, 0);
    m_tasks.push_front(UrlTask(url, file, status, &m_manager, this));
    endInsertRows();
}

void UrlTasks::delete_task_at(const QModelIndex &index)
{
    beginRemoveRows(QModelIndex(), index.row(), index.row());
    m_tasks.removeAt(index.row());
    endRemoveRows();
}

void UrlTasks::item_changed(const UrlTask &task)
{
    int i = m_tasks.indexOf(task);
    if (i != -1)
    {
        QModelIndex left = index(i, 0);
        QModelIndex right = index(i, UrlTask::LAST - 1);
        emit dataChanged(left, right);
    }
}
